package com.email.box.utils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.email.box.common.vo.FilteredParameter;


import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import static com.email.box.utils.TimeUtil.addOneDay;

public class FilteredUtil {

    private static List<String> parseListString(String s) {
        if (s == null || s.equals("")) {
            return new ArrayList<>();
        }
        try {
            return Arrays.asList(s.split(","));
        } catch (NumberFormatException x) {
            return new ArrayList<>();
        }
    }

    public static <T> QueryWrapper<T> getQueryWrapper(FilteredParameter filteredParameter) {

        String order = filteredParameter.getOrder();
        String searchField = filteredParameter.getSearchField();
        String searchType = filteredParameter.getSearchType();
        String searchWord = filteredParameter.getSearchWord();
        String responseField = filteredParameter.getResponseField();

        QueryWrapper<T> queryWrapper = new QueryWrapper<>();

        // TODO: response_field
        if (responseField != null && !responseField.equals("")) {
            queryWrapper.select(responseField);
        }


        // queryWrapper.select("status");
        List<String> fields = parseListString(searchField);
        List<String> types = parseListString(searchType);
        List<String> words = parseListString(searchWord);
        for (int i = 0; i < fields.size(); i++) {
            String field = fields.get(i);
            String word = words.get(i);
            String type = types.get(i);
            try {
                field = java.net.URLDecoder.decode(field, "UTF-8");
                word = java.net.URLDecoder.decode(word, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            if (type.equals("0")) { //精准(单选)
                queryWrapper.eq(field, word);
            } else if (type.equals("1")) { //包含(单选)
                queryWrapper.like(field, word);
            } else if (type.equals("2") || type.equals("5")) {
                //包含(多选)&精准(多选)
                multiSearch(field, word, type, queryWrapper);
            } else if (types.get(i).equals("3")) { //数字区间
                interval(queryWrapper, field, word, 3);
            } else if (types.get(i).equals("4")) { //时间区间
                word = word.substring(0, 23);
                interval(queryWrapper, field, word, 4);
            }
        }

        if (order != null && !order.equals("")) {
            String orderField = order.replaceFirst("^-", "");
            String orderType = order.startsWith("-") ? "descend" : "ascend";
            if (orderType.equals("descend")) {
                queryWrapper.orderByDesc(orderField);
            } else {
                queryWrapper.orderByAsc(orderField);
            }
        }

        return queryWrapper;
    }

    private static <T> void multiSearch(String field, String word, String type, QueryWrapper<T> queryWrapper) {
        String[] split = word.split("\\|");
        queryWrapper.and(obj -> {
            if (type.equals("5")) {
                obj.eq(field, split[0]);
                for (int j = 1; j < split.length; j++) {
                    obj.or().eq(field, split[j]);
                }
            } else if (type.equals("2")) {
                obj.like(field, split[0]);
                for (int j = 1; j < split.length; j++) {
                    obj.or().like(field, split[j]);
                }
            }
        });
    }

    public static <T> void interval(QueryWrapper<T> queryWrapper, String field, String word, int t) {
        //是否除外
        boolean isExcept = false;
        if (String.valueOf(word.charAt(0)).equals("!")) {
            isExcept = true;
            word = word.substring(1);
        }

        //左括号
        String left = String.valueOf(word.charAt(0));
        //右括号
        String right = String.valueOf(word.charAt(word.length() - 1));
        //去括号
        String str = word.substring(1, word.length() - 1);
        //通过"~"分割
        String[] strs = str.split("~");
        //左值
        String lv = strs[0];
        //右值
        String rv = "";
        if (strs.length > 1) {
            rv = strs[1];
            if (t == 4) {
                try {
                    rv = addOneDay(rv);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        if (isExcept) {
            //lambda要常量 所以要吧rv再赋值一遍
            String rv1 = rv;
            String field1 = field;
            if (!lv.equals("") && !rv.equals("") && left.equals("[") && right.equals("]")) {
                //区间]包含[
                queryWrapper.and(obj -> obj.gt(field1, rv1).or().lt(field1, lv));
            }

            if (!lv.equals("") && !rv.equals("") && left.equals("(") && right.equals(")")) {
                //区间)包含(
                queryWrapper.and(obj -> obj.ge(field1, rv1).or().le(field1, lv));
            }
            if (!lv.equals("") && !rv.equals("") && left.equals("[") && right.equals(")")) {
                //区间]包含(
                queryWrapper.and(obj -> obj.ge(field1, rv1).or().lt(field1, lv));
            }

            if (!lv.equals("") && !rv.equals("") && left.equals("(") && right.equals("]")) {
                //区间)包含[
                queryWrapper.and(obj -> obj.gt(field1, rv1).or().le(field1, lv));
            }
        } else {
            if (lv.equals("") && right.equals("]")) {
                //<=
                queryWrapper.le(field, rv);
            }
            if (rv.equals("") && left.equals("[")) {
                //>=
                queryWrapper.ge(field, lv);
            }
            if (lv.equals("") && right.equals(")")) {
                //<
                queryWrapper.lt(field, rv);
            }
            if (rv.equals("") && left.equals("(")) {
                //>
                queryWrapper.gt(field, lv);
            }
            if (!lv.equals("") && !rv.equals("") && left.equals("[") && right.equals("]")) {
                //区间[包含]
                queryWrapper.ge(field, lv);
                queryWrapper.le(field, rv);
            }
            // TODO: response_field
            // queryWrapper.select("status");

            if (!lv.equals("") && !rv.equals("") && left.equals("(") && right.equals(")")) {
                //区间(包含)
                queryWrapper.gt(field, lv);
                queryWrapper.lt(field, rv);
            }
            if (!lv.equals("") && !rv.equals("") && left.equals("[") && right.equals(")")) {
                //区间[包含)
                queryWrapper.ge(field, lv);
                queryWrapper.lt(field, rv);
            }

            if (!lv.equals("") && !rv.equals("") && left.equals("(") && right.equals("]")) {
                //区间(包含]
                queryWrapper.gt(field, lv);
                queryWrapper.le(field, rv);
            }

        }
    }

    public static <T> Page<T> getPage(FilteredParameter filteredParameter) {
        return new Page<>(filteredParameter.getPage(), filteredParameter.getLimit());
    }

    public static List<String> removeFilteredParameter(FilteredParameter filteredParameter, String parameter) {
        String searchField = filteredParameter.getSearchField();
        String searchType = filteredParameter.getSearchType();
        String searchWord = filteredParameter.getSearchWord();
        List<String> fields = new ArrayList<>(parseListString(searchField));

        List<String> types = new ArrayList<>(parseListString(searchType));
        List<String> words = new ArrayList<>(parseListString(searchWord));
        String fieldToRemove = null;
        String typeToRemove = null;
        String wordToRemove = null;
        int counter = 0;
        Iterator<String> iterator = fields.iterator();
        while (iterator.hasNext()) {
            if (iterator.next().equals(parameter)) {
                fieldToRemove = parameter;
                iterator.remove();
                typeToRemove = types.remove(counter);
                wordToRemove = words.remove(counter);
                break;
            }
            counter++;
        }

        filteredParameter.setSearchField(String.join(",", fields));
        filteredParameter.setSearchType(String.join(",", types));
        filteredParameter.setSearchWord(String.join(",", words));

        if (fieldToRemove != null && typeToRemove != null && wordToRemove != null) {
            return Arrays.asList(fieldToRemove, typeToRemove, wordToRemove);
        }
        return new ArrayList<>();
    }
}
